package aorm

import (
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"sync"
	"time"
)

// 新增
var (
	errorLog = log.New(os.Stdout, "\033[31m[error]\033[0m ", log.LstdFlags|log.Lshortfile)
	infoLog  = log.New(os.Stdout, "\033[34m[info ]\033[0m ", log.LstdFlags|log.Lshortfile)
	loggers  = []*log.Logger{errorLog, infoLog}
	mu       sync.Mutex

)

// log methods 新增
var (
	Error  = errorLog.Println
	Errorf = errorLog.Printf
	Info   = infoLog.Println
	Infof  = infoLog.Printf
)

// log levels 新增
const (
	InfoLevel = iota
	ErrorLevel
	Disabled
)

var logger *Logger

const (
	// LogSQL ...
	LogSQL LogLevel = iota
	// LogSlow ...
	LogSlow // 慢日志
	// LogError ...
	LogError
)

type (
	LogLevel uint

	LogOption struct {
		FilePath     string
		EnableSqlLog bool
		EnableSlowLog  float64 // 是否记录慢查询, 默认0s, 不记录, 设置记录的时间阀值, 比如 1, 则表示超过1s的都记录
		EnableErrorLog bool
	}

	Logger struct {
		log.Logger
		filePath string
		slowLog  float64
		sqlLog   bool
		errLog   bool
	}
)

// NewLogger ...
func NewLogger(o *LogOption) *Logger {
	//onceLogger.Do(func() {
	logger = &Logger{filePath: "./"}
	if o.FilePath != "" {
		logger.filePath = o.FilePath
	}
	logger.sqlLog = o.EnableSqlLog
	logger.slowLog = o.EnableSlowLog
	logger.errLog = o.EnableErrorLog
	//})
	return logger
}

// DefaultLogger 默认日志记录器。
func DefaultLogger() func(e *Engine) {
	return func(e *Engine) {
		e.logger = NewLogger(&LogOption{})
	}
}

// String ...
func (l LogLevel) String() string {
	switch l {
	case LogSQL:
		return "SQL"
	case LogSlow:
		return "SLOW"
	case LogError:
		return "ERROR"
	}
	return ""
}

// EnableSqlLog ...
func (l *Logger) SqlLog() bool {
	return l.sqlLog
}

// EnableErrorLog ...
func (l *Logger) ErrorLog() bool {
	return l.errLog
}

// EnableSlowLog ...
func (l *Logger) SlowLog() float64 {
	return l.slowLog
}

// Slow ...
func (l *Logger) Slow(sqlStr string, runtime time.Duration) {

	if l.SlowLog() > 0 &&  l.SlowLog() < runtime.Seconds() {
		logger.write(LogSlow, "orm_slow", sqlStr, runtime.String())
	}
}

// Sql ...
func (l *Logger) Sql(sqlStr string, runtime time.Duration) {
	if l.SqlLog() {
		logger.write(LogSQL, "orm_sql", sqlStr, runtime.String())
	}
}

// Error ...
func (l *Logger) Error(msg string) {
	if l.ErrorLog() {
		logger.write(LogError, "orm_err", msg, "0")
	}
}

func (l *Logger) write(ll LogLevel, filename string, msg string, runtime string) {
	now := time.Now()
	date := now.Format("20060102")
	datetime := now.Format("2006-01-02 15:04:05")
	f := readFile(fmt.Sprintf("%s/%v_%v.log", l.filePath, date, filename))
	content := fmt.Sprintf("[%v] [%v] %v --- %v\n", ll.String(), datetime, runtime, msg)
	withLockContext(func() {
		defer f.Close()
		buf := []byte(content)
		f.Write(buf)
	})
}

// 新增 函数
func SetLevel(level int) {
	mu.Lock()
	defer mu.Unlock()

	for _, logger := range loggers {
		logger.SetOutput(os.Stdout)
	}

	if ErrorLevel < level {
		errorLog.SetOutput(ioutil.Discard)
	}
	if InfoLevel < level {
		infoLog.SetOutput(ioutil.Discard)
	}
}
